home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / gpp-1_42.lha / g++-1.42.0 / collect2.c < prev    next >
C/C++ Source or Header  |  1991-10-19  |  6KB  |  262 lines

  1. /* Build tables of static constructors and destructors and run ld. */
  2.  
  3. #include <stdio.h>
  4.  
  5. #ifdef convex
  6.  
  7. #define TEXT_SECTION_ASM_OP ".text"
  8. #define DATA_SECTION_ASM_OP ".data"
  9.  
  10. #define ASM_GLOBALIZE_LABEL(FILE, LABEL) \
  11.   fprintf (FILE, ".globl _%s\n", LABEL)
  12.  
  13. #define ASM_OUTPUT_LABEL(FILE, LABEL) \
  14.   fprintf (FILE, "_%s:", LABEL)
  15.  
  16. #define ASM_OUTPUT_LABELREF(FILE, LABEL) \
  17.   fprintf (FILE, "\tds.w _%s\n", LABEL)
  18.  
  19. #define ASM_OUTPUT_INT(FILE, INT) \
  20.   fprintf (FILE, "\tds.w %d\n", INT)
  21.  
  22. #endif
  23.  
  24. #ifdef MASSCOMP
  25.  
  26. #define TEXT_SECTION_ASM_OP ".text"
  27. #define DATA_SECTION_ASM_OP ".data"
  28.  
  29. #define ASM_GLOBALIZE_LABEL(FILE, LABEL) \
  30.   fprintf (FILE, ".globl _%s\n", LABEL)
  31.  
  32. #define ASM_OUTPUT_LABEL(FILE, LABEL) \
  33.   fprintf (FILE, "_%s:\n", LABEL)
  34.  
  35. #define ASM_OUTPUT_LABELREF(FILE, LABEL) \
  36.   fprintf (FILE, "\t.long _%s\n", LABEL)
  37.  
  38. #define ASM_OUTPUT_INT(FILE, INT) \
  39.   fprintf (FILE, "\t.long %d\n", INT)
  40.  
  41. #endif
  42.  
  43. #if defined (__GNUC__) || defined (sparc)
  44. #define alloca __builtin_alloca
  45. #endif
  46.  
  47. extern char *mktemp (char *template);
  48.  
  49. /* Linked lists of constructor and destructor names. */
  50.  
  51. struct id 
  52. {
  53.   char *name;
  54.   struct id *next;
  55. };
  56.  
  57. /* Main program. */
  58.  
  59. main (int argc, char *argv[])
  60. {
  61.   static char codexxx[] = "/tmp/codeXXXXXX";
  62.   static char asxxx[] = "/tmp/asXXXXXX";
  63.   char *codefile, *hookfile, hooksfile[40], hookofile[40];
  64.   char *outfile = "a.out";
  65.   char *arg, ldargs[1024], cmd[1024];
  66.   FILE *inf, *outf;
  67.  
  68.   /* Make temp file names. */
  69.  
  70.   codefile = mktemp (codexxx);
  71.   hookfile = mktemp (asxxx);
  72.   sprintf (hooksfile, "%s.s", hookfile);
  73.   sprintf (hookofile, "%s.o", hookfile);
  74.  
  75.   /* Parse arguments.  Remove output file spec, pass the rest to ld. */
  76.  
  77.   ldargs[0] = '\0';
  78.   while (arg = *++argv)
  79.     {
  80.       if (! strcmp (arg, "-o"))
  81.     outfile = *++argv;
  82.       else
  83.     {
  84. #ifdef masscomp
  85.           if ( *arg == '-' && *(arg+1) == 'L' )
  86.         {
  87.           strcat (ldargs, " -L ");
  88.           strcat (ldargs, arg+2);
  89.         }
  90.       else
  91.         {
  92.           strcat (ldargs, " ");
  93.           strcat (ldargs, arg);
  94.         }
  95. #else
  96.       strcat (ldargs, " ");
  97.       strcat (ldargs, arg);
  98. #endif
  99.     }
  100.     }
  101.  
  102.   /* Load the program, searching all libraries.
  103.      Use -r to save the output as a relocatable file.
  104.      Examine the namelist with nm and search it for static constructors
  105.      and destructors to call.
  106.      Write the constructor and destructor tables to a .s file. */
  107.  
  108. #ifdef masscomp
  109. /*
  110.   sprintf (cmd, "ld -r -o %s %s", codefile, ldargs);
  111.   if (system(cmd))
  112.      fatal( "##F-ld: Cannot perform link." );
  113.   sprintf (cmd, "nm -p %s", codefile);
  114. */
  115.   sprintf (cmd, "ld -r -o %s %s && nm -p %s", codefile, ldargs, codefile);
  116. #else
  117.   sprintf (cmd, "ld -r -o %s %s && nm -p %s", codefile, ldargs, codefile);
  118. #endif
  119.  
  120.   if (! (inf = popen (cmd, "r")))
  121.     fatal_perror ("Can't open pipe to ld\n");
  122.   if (! (outf = fopen (hooksfile, "w")))
  123.     fatal_perror ("Can't write %s\n", hooksfile);
  124.  
  125.   write_hooks (inf, outf);
  126.  
  127.   if (pclose (inf) || fclose (outf))
  128.     fatal ("load failed");
  129.  
  130.   /* Assemble the constructor and destructor tables.
  131.      Link the tables in with the rest of the program. */
  132.  
  133.   sprintf (cmd, "as -o %s %s && ld -o %s %s %s && rm %s %s %s",
  134.        hookofile, hooksfile, 
  135.        outfile, codefile, hookofile,
  136.        codefile, hooksfile, hookofile);
  137.   exit (system (cmd));
  138. }
  139.  
  140. /* Scan the name list of the loaded program for the symbols g++ uses
  141.    for static constructors and destructors.  Write their addresses
  142.    into tables which __main and exit will call.
  143.  
  144.    The constructor table __CTOR_LIST__ is an integer count followed by
  145.    that many pointers to constructor functions.  The destructor table
  146.    __DTOR_LIST__ is the same thing, followed by a zero word. */
  147.  
  148. write_hooks (FILE *inf, FILE *outf)
  149. {
  150.   char *p, buf[1024];
  151.   struct id *newid;
  152.  
  153.   struct id *constructors = 0;
  154.   struct id *destructors = 0;
  155.  
  156.   while (! feof (inf)) {
  157.  
  158.     /* Read a line of nm output and strip the trailing newline. */
  159.  
  160.     fgets (buf, sizeof buf, inf);
  161.     p = buf + strlen (buf) - 1;
  162.     if (*p == '\n')
  163.       *p = '\0';
  164.  
  165. #ifdef masscomp
  166.     /* If loader spits out an error/warning message then
  167.     ** lets display it.
  168.     */
  169.     if (buf[0] == '#' && buf[1] == '#')
  170.       {
  171.     fprintf( stderr, "%s\n", buf );
  172.     buf[0] = '\0';
  173.       }
  174. #endif
  175.  
  176.     /* If it contains a constructor or destructor name, add the name
  177.        to the appropriate list. */
  178.  
  179.     for (p = buf; *p; p++)
  180.       {
  181.     while (*p && *p != '_')
  182.       p++;
  183.     if (! strncmp (p, "_GLOBAL_$I$", 11))
  184.       {
  185.         newid = alloca (sizeof *newid);
  186.         newid->name = alloca (strlen (p) + 1);
  187.         strcpy (newid->name, p);
  188.         newid->next = constructors;
  189.         constructors = newid;
  190.         break;
  191.       }
  192.     else if (! strncmp (p, "_GLOBAL_$D$", 11))
  193.       {
  194.         newid = alloca (sizeof *newid);
  195.         newid->name = alloca (strlen (p) + 1);
  196.         strcpy (newid->name, p);
  197.         newid->next = destructors;
  198.         destructors = newid;
  199.         break;
  200.       }
  201.       }
  202.   }
  203.  
  204.   /* Write the tables. */
  205.  
  206.   fprintf (outf, "%s\n", TEXT_SECTION_ASM_OP);
  207.   ASM_GLOBALIZE_LABEL (outf, "__CTOR_LIST__");
  208.   ASM_OUTPUT_LABEL (outf, "__CTOR_LIST__");
  209.   ASM_OUTPUT_INT (outf, count_list (constructors));
  210.   write_list (outf, constructors);
  211.   
  212.   fprintf (outf, "%s\n", DATA_SECTION_ASM_OP);
  213.   ASM_GLOBALIZE_LABEL (outf, "__DTOR_LIST__");
  214.   ASM_OUTPUT_LABEL (outf, "__DTOR_LIST__");
  215.   ASM_OUTPUT_INT (outf, count_list (destructors));
  216.   write_list (outf, destructors);
  217.   ASM_OUTPUT_INT (outf, 0);
  218. }
  219.  
  220. /* Length of list LIST. */
  221.  
  222. count_list (struct id *list)
  223. {
  224.   int count = 0;
  225.   while (list)
  226.     {
  227.       count++;
  228.       list = list->next;
  229.     }
  230.   return count;
  231. }
  232.  
  233. /* Write the names on list LIST, in reverse order. */
  234.  
  235. write_list (FILE *outf, struct id *list)
  236. {
  237.   if (! list)
  238.     return;
  239.   write_list (outf, list->next);
  240.   ASM_OUTPUT_LABELREF (outf, list->name);
  241. }
  242.  
  243. /* Die when sys call fails. */
  244.  
  245. fatal_perror (string, arg)
  246. {
  247.   char buf[80];
  248.   sprintf (buf, string, arg);
  249.   perror (buf);
  250.   exit (1);
  251. }
  252.  
  253. /* Just die. */
  254.  
  255. fatal (string)
  256. {
  257.   fprintf (stderr, "\n");
  258.   fprintf (stderr, string);
  259.   fprintf (stderr, "\n");
  260.   exit (1);
  261. }
  262.